package se.webbzon.boltzmann.minigame;

import java.awt.Color;
import java.awt.Font;
import java.awt.Rectangle;
import java.util.ArrayList;
import java.util.Collection;

import se.webbzon.boltzmann.minigame.sandbox.DefaultSandBoxItem;
import se.webbzon.boltzmann.minigame.sandbox.SandBox;
import se.webbzon.boltzmann.minigame.sandbox.SandBoxIcon;
import se.webbzon.boltzmann.minigame.sandbox.SandBoxObject;
import se.webbzon.boltzmann.resource.Resources;
import se.webbzon.oschi01.font.HorizontalAlignment;
import se.webbzon.oschi01.font.VerticalAlignment;
import se.webbzon.oschi01.utilities.StringUtils;
import se.webbzon.oschi01.worldarea.WorldArea;
import se.webbzon.oschi01.worldcamera.WorldCameraPane;
import se.webbzon.oschi01.worldobject.WorldObject;

public class Chronograph extends DefaultSandBoxItem {
	
	// The 2-dimensional depth of this timer
	private static final int depth2d = 10;
	
	// The font used for the chronograph
	private static final Font font = Resources.getFont("larabie_plain").deriveFont(16f);
	
	// A collections of all the listeners to this chronograph
	private final Collection<ChronographListener> listeners;
	
	// The dimension of the sand box
	private final Rectangle r;
	
	// The number of steps counted (or remaining) and the count speed
	// a positive count speed will make the steps increase and a negative
	// count speed will make the steps decrease.
	private double steps;
	private double speed;
	
	/*============================================================
	Constructors
	============================================================*/
	
	public Chronograph() {
		listeners = new ArrayList<ChronographListener>();
		r = new Rectangle();
		setInstance(new Instance());
		steps = 0;
		speed = 1;
	}
	
	/*============================================================
	Public Methods
	============================================================*/
	
	/** Restes the chonograph to the given time. **/
	public void reset(int time) {
		this.steps = time < 0 ? 0 : time;
	}
	
	/** Returns the speed of the chronograph. **/
	public double getSpeed() {
		return speed;
	}
	
	/** Sets the speed of the chronograph. **/
	public void setSpeed(double speed) {
		this.speed = speed;
	}
	
	/** Adds a listener to this chronograph. **/
	public boolean addListener(ChronographListener listener) {
		return listeners.add(listener);
	}
	
	/** Removes a listener from this chronograph. **/
	public boolean removeListener(ChronographListener listener) {
		return listeners.remove(listener);
	}
	
	/** Clears all the listeners from this chronograph. **/
	public void clearListeners() {
		listeners.clear();
	}
	
	/*============================================================
	Private Methods
	============================================================*/
	
	/** Converts the provided time to a string. **/
	private static String toString(double time, int stepsPerSecond) {
		int seconds = (int) (time / stepsPerSecond);
		double rest = time / (double) stepsPerSecond - seconds;
		int restTrunc = (int) (rest * 100);
		int minutes = seconds / 60;
		seconds = seconds - minutes * 60;
		return StringUtils.leadPadding(Integer.toString(minutes),2,'0') + ":" + 
				StringUtils.leadPadding(Integer.toString(seconds),2,'0') + ":" + 
				StringUtils.leadPadding(Integer.toString(restTrunc),2,'0');
	}
	
	/*============================================================
	Private Classes
	============================================================*/
	
	private final class Instance extends SandBoxObject {

		public Instance() {
			super(WorldObject.onStep + WorldObject.onPostDraw, depth2d);
		}

		@Override public void onAttach(SandBox box) {
			box.getBoundary(r);
		}

		@Override public void onDetach(SandBox box) {};
		
		@Override public void onStep(WorldArea world) {
			if (steps > 0 && speed < 0) {
				if (steps <= speed) {
					for (ChronographListener listener : listeners.toArray(new ChronographListener[0]))
						listener.onAlarm(Chronograph.this);
					steps = 0;
				} else
					steps += speed;
			} else if (speed > 0)
				steps += speed;
		}

		@Override public void onPostDraw(WorldArea world, WorldCameraPane hud) {
			hud.setHAlignment(HorizontalAlignment.RIGHT);
			hud.setVAlignment(VerticalAlignment.TOP);
			hud.setColor(Color.black);
			hud.setFont(font);
			int x = (int) r.getWidth() - 4;
			int y = 4;
			String str = Chronograph.toString(steps,40);
			hud.drawString(str, x, y);
			hud.setColor(Color.white);
			hud.drawString(str, x - 1, y - 1);
		}

		@Override public SandBoxIcon createIcon() {
			return null;
		}
		
	}

}
